"""
System Log Model
系统日志模型 - 系统日志和审计功能
"""

import uuid
from enum import Enum

from sqlalchemy import Column, String, DateTime, Integer, Boolean, Text, ForeignKey, JSON
from sqlalchemy.dialects.postgresql import UUID
from sqlalchemy.sql import func
from sqlalchemy.orm import relationship

from ..core.database import Base


class LogLevel(str, Enum):
    """日志级别枚举"""
    DEBUG = "DEBUG"
    INFO = "INFO"
    WARNING = "WARNING"
    ERROR = "ERROR"
    CRITICAL = "CRITICAL"


class LogCategory(str, Enum):
    """日志分类枚举"""
    SYSTEM = "system"              # 系统日志
    USER_ACTIVITY = "user_activity" # 用户活动
    AUTHENTICATION = "authentication" # 认证相关
    AUTHORIZATION = "authorization"   # 授权相关
    CONTENT_GENERATION = "content_generation" # 内容生成
    FILE_OPERATION = "file_operation" # 文件操作
    DATABASE = "database"          # 数据库操作
    API_REQUEST = "api_request"    # API请求
    ERROR = "error"               # 错误日志
    SECURITY = "security"         # 安全相关
    PERFORMANCE = "performance"   # 性能相关
    TASK_QUEUE = "task_queue"     # 任务队列
    EXTERNAL_SERVICE = "external_service" # 外部服务


class LogSource(str, Enum):
    """日志来源枚举"""
    WEB_API = "web_api"           # Web API
    DESKTOP_APP = "desktop_app"   # 桌面应用
    BACKGROUND_WORKER = "background_worker" # 后台工作进程
    SYSTEM_SERVICE = "system_service" # 系统服务
    DATABASE = "database"         # 数据库
    EXTERNAL_SERVICE = "external_service" # 外部服务


class SystemLog(Base):
    """系统日志模型"""

    __tablename__ = "system_logs"

    id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
    
    # 关联信息
    user_id = Column(
        UUID(as_uuid=True), 
        ForeignKey("users.id", ondelete="SET NULL"), 
        nullable=True,
        index=True
    )
    
    related_content_id = Column(
        UUID(as_uuid=True), 
        ForeignKey("generated_contents.id", ondelete="SET NULL"), 
        nullable=True,
        index=True
    )
    
    related_request_id = Column(
        UUID(as_uuid=True), 
        ForeignKey("creation_requests.id", ondelete="SET NULL"), 
        nullable=True,
        index=True
    )
    
    related_task_id = Column(
        UUID(as_uuid=True), 
        ForeignKey("task_queues.id", ondelete="SET NULL"), 
        nullable=True,
        index=True
    )

    # 日志基本信息
    level = Column(String(10), nullable=False, index=True)  # DEBUG, INFO, WARNING, ERROR, CRITICAL
    category = Column(String(30), nullable=False, default="system", index=True)
    source = Column(String(30), nullable=False, default="web_api")
    
    # 日志内容
    message = Column(Text, nullable=False)
    detail_message = Column(Text, nullable=True)  # 详细消息
    
    # 错误信息
    error_type = Column(String(100), nullable=True)  # 错误类型
    error_code = Column(String(50), nullable=True)  # 错误代码
    stack_trace = Column(Text, nullable=True)  # 堆栈跟踪
    
    # 上下文信息
    request_id = Column(String(100), nullable=True, index=True)  # 请求ID
    session_id = Column(String(100), nullable=True, index=True)  # 会话ID
    trace_id = Column(String(100), nullable=True, index=True)  # 追踪ID
    span_id = Column(String(100), nullable=True)  # Span ID
    
    # 位置信息
    file_path = Column(String(500), nullable=True)  # 文件路径
    function_name = Column(String(100), nullable=True)  # 函数名
    line_number = Column(Integer, nullable=True)  # 行号
    module_name = Column(String(100), nullable=True)  # 模块名
    
    # 环境信息
    environment = Column(String(20), default="development")  # 环境
    application_version = Column(String(50), nullable=True)  # 应用版本
    
    # 客户端信息
    client_ip = Column(String(45), nullable=True)  # 客户端IP
    user_agent = Column(String(500), nullable=True)  # 用户代理
    device_info = Column(String(200), nullable=True)  # 设备信息
    platform = Column(String(50), nullable=True)  # 平台信息
    
    # 性能信息
    execution_time_ms = Column(Integer, nullable=True)  # 执行时间（毫秒）
    memory_usage_mb = Column(Integer, nullable=True)  # 内存使用（MB）
    cpu_usage_percent = Column(Integer, nullable=True)  # CPU使用百分比
    
    # 业务信息
    action = Column(String(100), nullable=True)  # 操作动作
    resource_type = Column(String(50), nullable=True)  # 资源类型
    resource_id = Column(String(100), nullable=True)  # 资源ID
    operation_result = Column(String(20), nullable=True)  # 操作结果
    
    # 安全信息
    security_level = Column(String(20), nullable=True)  # 安全级别
    is_security_event = Column(Boolean, default=False)  # 是否为安全事件
    security_category = Column(String(50), nullable=True)  # 安全分类
    
    # 元数据
    content_metadata = Column(JSON, default=dict)  # 其他元数据（避免与SQLAlchemy的metadata冲突）
    tags = Column(JSON, default=list)  # 标签
    
    # 时间戳
    timestamp = Column(DateTime, default=func.now(), index=True)
    created_at = Column(DateTime, default=func.now())

    # 关系
    user = relationship("User", back_populates="system_logs")
    related_content = relationship("GeneratedContent", back_populates="system_logs")
    related_request = relationship("CreationRequest", back_populates="system_logs")
    related_task = relationship("TaskQueue", back_populates="system_logs")

    def __repr__(self):
        return f"<SystemLog(id={self.id}, level={self.level}, category={self.category}, message={self.message[:50]}...)>"

    @property
    def is_error(self) -> bool:
        """是否为错误日志"""
        return self.level in [LogLevel.ERROR, LogLevel.CRITICAL]

    @property
    def is_warning(self) -> bool:
        """是否为警告日志"""
        return self.level == LogLevel.WARNING

    @property
    def is_security_log(self) -> bool:
        """是否为安全日志"""
        return self.is_security_event or self.category == LogCategory.SECURITY

    @property
    def is_user_activity(self) -> bool:
        """是否为用户活动日志"""
        return self.category == LogCategory.USER_ACTIVITY

    @property
    def has_error_details(self) -> bool:
        """是否有错误详情"""
        return bool(self.error_type or self.error_code or self.stack_trace)

    @property
    def has_performance_data(self) -> bool:
        """是否有性能数据"""
        return bool(
            self.execution_time_ms is not None or
            self.memory_usage_mb is not None or
            self.cpu_usage_percent is not None
        )

    @property
    def has_client_info(self) -> bool:
        """是否有客户端信息"""
        return bool(
            self.client_ip or
            self.user_agent or
            self.device_info or
            self.platform
        )

    def get_error_summary(self) -> dict:
        """获取错误摘要"""
        if not self.is_error:
            return {}
        
        return {
            "error_type": self.error_type,
            "error_code": self.error_code,
            "message": self.message,
            "detail_message": self.detail_message,
            "stack_trace": self.stack_trace,
            "file_path": self.file_path,
            "function_name": self.function_name,
            "line_number": self.line_number,
        }

    def get_performance_summary(self) -> dict:
        """获取性能摘要"""
        if not self.has_performance_data:
            return {}
        
        return {
            "execution_time_ms": self.execution_time_ms,
            "memory_usage_mb": self.memory_usage_mb,
            "cpu_usage_percent": self.cpu_usage_percent,
        }

    def get_client_summary(self) -> dict:
        """获取客户端摘要"""
        if not self.has_client_info:
            return {}
        
        return {
            "client_ip": self.client_ip,
            "user_agent": self.user_agent,
            "device_info": self.device_info,
            "platform": self.platform,
        }

    def get_business_context(self) -> dict:
        """获取业务上下文"""
        return {
            "action": self.action,
            "resource_type": self.resource_type,
            "resource_id": self.resource_id,
            "operation_result": self.operation_result,
            "user_id": str(self.user_id) if self.user_id else None,
            "request_id": self.request_id,
            "session_id": self.session_id,
        }

    def add_tag(self, tag: str) -> None:
        """添加标签"""
        tags = self.tags or []
        if tag not in tags:
            tags.append(tag)
            self.tags = tags

    def remove_tag(self, tag: str) -> bool:
        """移除标签"""
        tags = self.tags or []
        if tag in tags:
            tags.remove(tag)
            self.tags = tags
            return True
        return False

    def set_error_details(self, error_type: str, error_code: str = None, stack_trace: str = None) -> None:
        """设置错误详情"""
        self.error_type = error_type
        if error_code:
            self.error_code = error_code
        if stack_trace:
            self.stack_trace = stack_trace

    def set_performance_data(self, execution_time_ms: int = None, memory_usage_mb: int = None, cpu_usage_percent: int = None) -> None:
        """设置性能数据"""
        if execution_time_ms is not None:
            self.execution_time_ms = execution_time_ms
        if memory_usage_mb is not None:
            self.memory_usage_mb = memory_usage_mb
        if cpu_usage_percent is not None:
            self.cpu_usage_percent = cpu_usage_percent

    def set_client_info(self, client_ip: str = None, user_agent: str = None, device_info: str = None, platform: str = None) -> None:
        """设置客户端信息"""
        if client_ip:
            self.client_ip = client_ip
        if user_agent:
            self.user_agent = user_agent
        if device_info:
            self.device_info = device_info
        if platform:
            self.platform = platform

    def set_business_context(self, action: str, resource_type: str = None, resource_id: str = None, operation_result: str = None) -> None:
        """设置业务上下文"""
        self.action = action
        if resource_type:
            self.resource_type = resource_type
        if resource_id:
            self.resource_id = resource_id
        if operation_result:
            self.operation_result = operation_result

    def set_security_context(self, security_level: str, security_category: str = None) -> None:
        """设置安全上下文"""
        self.is_security_event = True
        self.security_level = security_level
        if security_category:
            self.security_category = security_category

    def set_location_context(self, file_path: str = None, function_name: str = None, line_number: int = None, module_name: str = None) -> None:
        """设置位置上下文"""
        if file_path:
            self.file_path = file_path
        if function_name:
            self.function_name = function_name
        if line_number is not None:
            self.line_number = line_number
        if module_name:
            self.module_name = module_name

    def to_dict(self, include_full_details: bool = False) -> dict:
        """转换为字典"""
        data = {
            "id": str(self.id),
            "level": self.level,
            "category": self.category,
            "source": self.source,
            "message": self.message,
            "timestamp": self.timestamp.isoformat() if self.timestamp else None,
            "user_id": str(self.user_id) if self.user_id else None,
            "request_id": self.request_id,
            "session_id": self.session_id,
            "trace_id": self.trace_id,
            "action": self.action,
            "resource_type": self.resource_type,
            "resource_id": self.resource_id,
        }
        
        if include_full_details:
            data.update({
                "detail_message": self.detail_message,
                "error_type": self.error_type,
                "error_code": self.error_code,
                "stack_trace": self.stack_trace,
                "client_ip": self.client_ip,
                "user_agent": self.user_agent,
                "device_info": self.device_info,
                "platform": self.platform,
                "execution_time_ms": self.execution_time_ms,
                "memory_usage_mb": self.memory_usage_mb,
                "cpu_usage_percent": self.cpu_usage_percent,
                "file_path": self.file_path,
                "function_name": self.function_name,
                "line_number": self.line_number,
                "module_name": self.module_name,
                "content_metadata": self.content_metadata or {},
                "tags": self.tags or [],
            })
        
        return data

    def to_log_entry(self) -> str:
        """转换为日志条目格式"""
        parts = [
            f"[{self.timestamp.isoformat() if self.timestamp else 'N/A'}]",
            f"[{self.level}]",
            f"[{self.category}]",
        ]
        
        if self.user_id:
            parts.append(f"[User:{self.user_id}]")
        
        if self.request_id:
            parts.append(f"[Req:{self.request_id}]")
        
        if self.action:
            parts.append(f"[Action:{self.action}]")
        
        parts.append(self.message)
        
        if self.detail_message:
            parts.append(f"({self.detail_message})")
        
        return " ".join(parts)


# 日志级别映射
LOG_LEVEL_MAPPING = {
    "DEBUG": LogLevel.DEBUG,
    "INFO": LogLevel.INFO,
    "WARNING": LogLevel.WARNING,
    "WARN": LogLevel.WARNING,
    "ERROR": LogLevel.ERROR,
    "CRITICAL": LogLevel.CRITICAL,
    "FATAL": LogLevel.CRITICAL,
}


def normalize_log_level(level: str) -> LogLevel:
    """标准化日志级别"""
    if isinstance(level, LogLevel):
        return level
    
    level_str = str(level).upper()
    return LOG_LEVEL_MAPPING.get(level_str, LogLevel.INFO)


def create_log_entry(
    level: str,
    message: str,
    category: str = "system",
    user_id: str = None,
    **kwargs
) -> SystemLog:
    """创建日志条目"""
    log_entry = SystemLog(
        level=normalize_log_level(level),
        message=message,
        category=category,
        user_id=user_id,
        **kwargs
    )
    return log_entry